package com.tedu.api.io;



import org.junit.Test;


import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.SQLOutput;


/**
 * 標準IO流----目的：數據傳輸  輸出文本，圖片
 * java定義一套標準流-->數據傳輸-->創建流：直接創建某個流對象
 * 標準流規則①：方向劃分  輸入流和輸出流
 *         輸入流：讀入-->文件-->相對於程序--->文件往程序走
 *         輸出流：寫出-->文件-->相對於程序--->程序寫出
 *         OutputStream(抽象類：定義所有寫的方法）
 *         ②：功能劃分
 *         低級流【節點流】：是建立在程序與數據源之間的”管道“
 *                  功能：負責搬運的數據流，輸入流于輸出流都有自己的低級流
 *                  特點：一個字節一個字節讀或者寫的方法
 *          FileOutputStream   低級流繼承InputStream---文件輸出流：寫
 *          FileInputStream   低級流繼承OutputStream---文件輸入流：讀
 *         高級流【處理流】：不能直接創建對象，不能獨立存在
 *                   功能：專門處理低級流一級其他高級流的流
 *                   特點：搬運數據時，實現具體的功能：效率提高流
 *
 * ---總結：輸出流和輸出流,具備功能：低級流與高級流,實際使用：明確使用具體的流
 * 實際使用：明確使用具體劉，每個劉都有自己功能
 *

 */
public class IOAPI {
    /**
     * 文件輸入流
     * 輸入流          低級流----
     * 標準流      方向           功能：        文件輸出流：FileOutputStream  √
     * 輸出流           高級流----
     * 需求：寫出一個文件fos.txt
     * <p>
     * FileOutputStream构造器使用
     * new FileOutputStream（“路径+文件全称”）
     * new FileOutputStream（“路径+文件全称”，boolean append）
     * 写出文件的同时实现追加效果，第二个参数：true 追加
     * false 默认不追加
     * new FileOutStream（File file，boolean  append）
     * 写出文件，采用File传入路径+全称
     */
    @Test
    public void testFOS() throws IOException {
   /* RandomAccessFile raf=
            new RandomAccessFile("fos.txt","r");*/
        //低級流---文件輸出流對象---從程序中寫出”文件：數據“
        FileOutputStream fos = new FileOutputStream("fos.txt", true);
        //需求：for.txt 增加一行文本
        String say = "獨一無二";
        //字符串由字符數組構成--數組的功能getBytes（）轉換為字節數組
        //輸出流--謝功能：write（byte[] b) 寫出字節數組
        fos.write(say.getBytes("UTF8"));
        //必须关闭流--目的：节省内存开销
        fos.close();
    }
    @Test
    public void testFOSIO(){
        FileOutputStream fos=null;
        BufferedOutputStream bos=null;
        try {
            fos=new FileOutputStream("fos.txt",true);
            bos=new BufferedOutputStream(fos);
            bos.write("你好".getBytes());
            bos.flush();
        } catch(FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch(Exception e){
            e.printStackTrace();
        } finally {
            if(bos!=null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * 文件输入流：读入操作
     * FileInputStream   文件输入流
     * read() 返回一个读取一个字节--效率低
     * read(字节数组byte[] b) 返回一个“指定字节数组:空间大小”的---效率高 √
     * 需求：读入fos.txt文件内容
     */
    @Test
    public void testFIS() throws IOException {
        //創建文件輸入流---讀入：fos.txt
        FileInputStream fis=new FileInputStream("fos.txt");

        //讀入效率高：創建字節數組-指定空間為：10KB
        byte[] data=new byte[1024*10];
        //读入操作：read(字节数组) | 以10KB读入数据
        int len=fis.read(data);
        //写出：文本----字符串--针对流操作，提供构造器
        //                   文件按照“指定字节数组空间”写入程序中
        //                   从0开始写入程序，写入到-1结束
        //                   len:十进制转换为二进制，写入，不等于-1，一直写入
        //一次性将给定数据按照字节数组指定空间大小，写出成字符串
        String str=new String(data,0,len);
        System.out.println("打印fos.txt文件:"+str);

    }
    @Test
    public void testFISIO(){
        FileInputStream fis=null;
        try {
            fis=new FileInputStream("fos.txt");
            byte[] data=new byte[1024*10];
            int len=fis.read(data);
            String str=new String(data,0,len);
            System.out.println("打印fos.txt文件:"+str);
        } catch(FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch(Exception e){
            e.printStackTrace();
        } finally {
            if(fis!=null)
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * 需求：利用标准流实现视频复制粘贴
     */
    @Test
    public void testCV() throws IOException {
        //1.从"复制文件.mp4" 复制 操作---读入
        FileInputStream fis=new FileInputStream("复制视频.mp4");
        //2.创建新文件"新文件.mp4" 粘贴 操作---写出
        FileOutputStream fos=new FileOutputStream("新文件.mp4");
        //3.保存每次读取的数据【字节量】
        int len = -1;
        //4.一直从“复制文件.mp4”进行读入操作,不等于-1一直读
        //（len=fis.read（））！=-1
        while ((len = fis.read()) != -1) {

            //4.1同时写出“新文件.mp4”
            fos.write(len);
        }
        //5.关闭流
        fis.close();fos.close();
    }
    @Test
    public void testCVIO(){
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try {
            fis=new FileInputStream("瓦.mp4");
            fos=new FileOutputStream("新文件.mp4");
            int len=-1;
            while(   (len=fis.read())!=-1   ){
                fos.write(len);
            }
        } catch(FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch(Exception e){
            e.printStackTrace();
        }finally {
            if(fos!=null)
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

    }
    /**
     * 需求：利用标准流实现视频复制粘贴---效率低
     *                               效率高--->空间执行为：自定  100KB
     *
     * 【高级流】BufferedInputStream  缓冲输入流--提升效率--缓冲区：字节数组【长度按照文件大小合理分配】
     *         BufferedOutputStream  缓冲输出流--提升效率--缓冲区：字节数组【长度按照文件大小合理分配】
     * 高级流使用方式：①处理低级流，套在低级流上
     *              ②直接使用高级流的方法
     *              ③高级流不能直接创建【不能独立存在】
     */
    @Test
    public void testCVS() throws IOException {
        //创建低级流：读入“复制视频”
        FileInputStream fis=new FileInputStream("复制视频.mp4");
        //创建高级流：套在低级流上【自带缓冲区：字节数组】
        BufferedInputStream bis=new BufferedInputStream(fis);
        //2.创建低级流：写出“高级效率.mp4”
        FileOutputStream fos=new FileOutputStream("高效视频.mp4");
        //2.创建高级流，套在低级流上【自带缓冲区：字节数组】
        BufferedOutputStream bos=new BufferedOutputStream(fos);

        //3.保存数据
        int len=-1;
        //4.高级流--低级流方法一致---read()读取内嵌缓冲区【字节数组】
        // 高级流--低级流方法一直--write（）写出内嵌缓冲区【字节数组】
        //  一直从“复制视频.mp4"读取数据，不等于-1，一直读
        //(len=bis.read())!=-1
        System.currentTimeMillis();//系统时间毫秒数
        while((len=bis.read())!=-1){
            bos.write(len);
        }
        long end=System.currentTimeMillis();

        long start=System.currentTimeMillis();
        System.out.println("缓冲流【自带缓冲区】："+(end+start)+"毫秒数");
        //关闭流--- 高级流与低级流：都关--->高级流间接性关闭低级流
        bis.close();//高级流--缓冲输入流
        bos.close();//高级流--缓冲输出流
    }
    @Test
    public void testCVSIO() throws FileNotFoundException {
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        try {
            fis = new FileInputStream("复制视频.mp4.mp4");
            bis = new BufferedInputStream(fis);
            fos = new FileOutputStream("搞笑视频.mp4");
            bos = new BufferedOutputStream(fos);
            int len = -1;
            while ((len = bis.read()) != -1) {
                bos.write(len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

        /**
         * 高级流----缓冲流【内嵌缓冲区】
         * BufferedOutputStream  缓冲输出流
         *
         * 需求：通过缓冲输出流实现从程序写出文件：bos.txt，写出内容
         */
    }
    @Test
    public void testBOS() throws IOException {
        //1.创建低级流-->bos.txt
        FileOutputStream fos=new FileOutputStream("bos.txt");
        //2.创建高级流-->缓冲区：字节数组--合理【传输效率】
        BufferedOutputStream bos=new BufferedOutputStream(fos);
        //3.写出文本内容
        String str="50 块钱设计再好看，也不如100块钱招人稀罕";
        //4.写出到 bos.txt 文件中:字符串转成字节数组--写出
        bos.write(str.getBytes());
        //5.将缓冲区数据一次性写出 flush（） [立即写出】
        //bos.flush();
        //A 你好  你认识我吗   干哈呢   ？？
        bos.close();  //关闭流----一定把缓冲区数据全部写出

    }



    /**
     * 标准IO---成对【低级流+高级流】结合异常---数据传输---成功【异常需要捕获】
     * 需求：重构testBOS（）  单元测试
     */
    @Test
    public void testBOSIO() throws IOException {
        //1.置空流---提升所有流作用域：使用范围
        FileOutputStream fos=null;//低级流：搬运数据
        BufferedOutputStream bos=null;//高级流：缓冲输出流
        //2.捕获流异常并且做出处理
        try {
            fos = new FileOutputStream("bos.txt");//低级流
            bos = new BufferedOutputStream(fos);//高级流：缓冲流：字节数组
            bos.write("独一无二".getBytes());
            bos.flush();
        }catch (FileNotFoundException e){//IO流”小“异常
            e.printStackTrace();
        } catch (IOException e){  //IO流  “中”异常，小异常父类
            e.printStackTrace();
        }catch (Exception e){  //IO流 ”大“异常 Exception
            e.printStackTrace();
        }
        finally { //一定执行
            //3.关闭流---高级流
            //判断：高级流不为null，关闭
            if (bos!=null)
            try {
                bos.close();
            }catch(IOException e){
                e.printStackTrace();
            }
            }
        }
    }


















